package com.crl.module.pool
{
	import com.crl.core.ClassFactory;
	import com.crl.core.IDispose;
	import com.crl.core.IPoolable;
	import com.crl.events.StateEvent;
	
	import flash.events.Event;
	
	
	/**
	 * 对像池;
	 * @author crl
	 * 
	 */	
	public class ObjectPool implements IDispose {
	
		
		/**
		 * 池大小; 
		 */		
		protected var _poolSize:uint;
		
		/**
		 * 对像存储池; 
		 */		
		protected var pool:Vector.<IPoolable>;

		protected var _factory:ClassFactory;
		
		
		/**
		 * 
		 * @param objectClass 对像类型
		 * @param poolSize 池大小;
		 * 
		 */		
		public function ObjectPool(factory:ClassFactory, poolSize:uint)
		{
			this._factory = factory;
			this._poolSize = poolSize;  

			pool = new Vector.<IPoolable>();
			addNewInstances(poolSize);
		}

		/**
		 *  对像池中所存储的对像类型;
		 * @return 
		 * 
		 */		
		public function get factory():ClassFactory {
			return _factory; 
		}
		
		/**
		 * 取得池大小;
		 * @return 
		 * 
		 */		
		public function get poolSize():uint {
			return _poolSize; 
		}
		
		/**
		 * 当前池中对像数量;
		 * @return 
		 * 
		 */		
		public function get length():uint {
			return pool.length; 
		}
		
		
		/**
		 *  取得一个缓存对像; 
		 * @return 
		 * 
		 */		
		public function get():*
		{
			var poolabel:IPoolable = pool.shift();
			
			if (pool.length == 0)
			{
				populate();
			}
			
			//弱引用,以便他不会所有其它人引用时,也不被当前的函数引用着,将被直接gc掉; 
			poolabel.addEventListener(StateEvent.SLEEP,onIPoolableInstanceSleepHandler,false,0,true);
			poolabel.awaken();
			
			
			return poolabel;
		}
		
		/**
		 *  当注销掉实例时,压入池; 
		 * @param event
		 * 
		 */		
		private function onIPoolableInstanceSleepHandler(event:Event):void{
			var poolabel:IPoolable=event.target as IPoolable;
			poolabel.removeEventListener(StateEvent.SLEEP,onIPoolableInstanceSleepHandler);
			this.set(poolabel);
		}
		
		
		/**
		 * 把对像压入池; 
		 * 
		 * 如果池已满,并不会成功加入;
		 * 
		 * 设为internal 让canche 类,可以访问到;
		 * @param object
		 * 
		 */		
		internal function set(poolabel:IPoolable):Boolean
		{
			if(poolabel==null)return false;
			
			if (pool.length < _poolSize && pool.indexOf(poolabel)==-1) {
				pool.push(poolabel);
				return true;
			}
			
			return false;
		}
		
		/**
		 * 尝试创建一个池类型对像;
		 * 
		 * 如果池已满,将不会创建;
		 */
		public function populate():Boolean
		{
			var num:uint = _poolSize - pool.length;
			if (num > 0) {
				addNewInstances(num);
				return true;
			}
			return false;
		}
		
		/**
		 * 清空池;
		 */
		public function dispose():void
		{
			pool.splice(0,pool.length);
		}
		
		
		/**
		 * 创建一定数量的类型对像, 
		 * @param num 数量;
		 * 
		 */		
		protected function addNewInstances(num:uint = 1):void
		{
			if (num < 1) return;
			for (var i:uint = 0 ;  i < num ; ++i)
			{
				pool.push(factory.newInstance());
			}
		}
	}
	
}